package com.baikeyang.common.netease;

import com.baikeyang.common.util.StringUtils;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class ParamUtil {

  public static String modulus = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7";
  public static String nonce = "0CoJUm6Qyw8W8jud";
  public static String pubKey = "010001";

  public static Map<String, Object> convertParam(String value) {
    Map<String, Object> result = new HashMap<String, Object>();
    String key = createSecretKey(16);
    result.put("params", getEncText(key, value));
    result.put("encSecKey", getEncSecKey(key));
    return result;
  }

  private static String getEncText(String key, String value) {
    String initVector = "0102030405060708"; // 16 bytes IV
    String en = encrypt(nonce, initVector, value);// nonce： 128 bit key    initVector：16 bytes IV
    String encText = encrypt(key, initVector, en);// key:随机生成的
    //System.out.println("encText:"+encText);
    return encText;
  }

  private static String getEncSecKey(String key) {
    String _text = new StringBuffer(key).reverse().toString();
    String[] _texts = _text.split("");
    String str = StringUtils.join(_texts, "");
    BigInteger biText = new BigInteger(strTo16(str), 16);
    BigInteger biEx = new BigInteger(pubKey, 16);
    BigInteger biMod = new BigInteger(modulus, 16);

    // create 3 BigInteger objects
    BigInteger biRet = biText.modPow(biEx, biMod);
    String encSecKey = biRet.toString(16);
    String s = zfill(encSecKey, 256);
    //System.out.println("encSecKey:" + s);
    return s;
  }

  private static String createSecretKey(int size) {
    String keys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    String key = "";
    for (int i = 0; i < size; i++) {
      double pos = Math.random() * keys.length();
      pos = Math.floor(pos);
      key = key + keys.charAt((int)pos);
    }
    return key;
  }

  private static String zfill(String str, Integer size) {
    while (str.length() < size) str = "0" + str;
    return str;
  }

  private static String encrypt(String key, String initVector, String value) {
    try {
//            System.out.println("key:\t" + Arrays.toString(key.getBytes("UTF-8")));
//            System.out.println("iv:\t" + Arrays.toString(initVector.getBytes("UTF-8")));
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
      SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      //Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

      byte[] encrypted = cipher.doFinal(value.getBytes());
      //System.out.println(Arrays.toString(encrypted));
//            System.out.println("encrypted string: "
//                    + Base64.encodeBase64String(encrypted));

      //return byte2HexStr(encrypted);
      return Base64.encodeBase64String(encrypted);
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return null;
  }

  private static String decrypt(String key, String initVector, String encrypted) {
    try {
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
      SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

      //byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
      byte[] original = cipher.doFinal(hexStr2Bytes(encrypted));

      return new String(original);
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return null;
  }

  /**
   *
   * 十六进制转换字符串
   */

  private static byte[] hexStr2Bytes(String hexStr) {
    System.out.println("in len :" + hexStr.length());
    String str = "0123456789ABCDEF";
    char[] hexs = hexStr.toCharArray();
    byte[] bytes = new byte[hexStr.length() / 2];
    int n;
    for (int i = 0; i < bytes.length; i++) {
      n = str.indexOf(hexs[2 * i]) * 16;
      n += str.indexOf(hexs[2 * i + 1]);
      bytes[i] = (byte) (n & 0xff);
    }
    System.out.println("out len :" + bytes.length);
    System.out.println("ddd" + Arrays.toString(bytes));
    return bytes;
  }

  /**
   * 字符串转化成为16进制字符串
   * @param s
   * @return
   */
  private static String strTo16(String s) {
    String str = "";
    for (int i = 0; i < s.length(); i++) {
      int ch = (int) s.charAt(i);
      String s4 = Integer.toHexString(ch);
      str = str + s4;
    }
    return str;
  }


  public static void main(String[] args) {
    String str = "{\"csrf_token\":\"\"}";
    Map<String, Object> resultMap = new HashMap<String, Object>();
    resultMap = ParamUtil.convertParam(str);
    System.out.println(resultMap.get("encText"));
    System.out.println(resultMap.get("encSecKey"));
  }

}
